package com.solution.service;

import java.util.Iterator;
import java.util.List;

import javax.ejb.EJBException;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;

import org.apache.log4j.Logger;
import org.jboss.annotation.ejb.RemoteBinding;

import com.solution.constant.ErrorMessages;
import com.solution.constant.ExamErrorMessages;
import com.solution.constant.StatusConstants;
import com.solution.dao.DAOFactory;
import com.solution.dao.ExamCategoryLevelMappingDAO;
import com.solution.dao.ExamTypeDAO;
import com.solution.exception.DAOException;
import com.solution.exception.ServiceBeanException;
import com.solution.model.ExamCategoryLevelMapping;
import com.solution.model.ExamType;
import com.solution.util.SearchVO;

@Stateless
@Remote(ExamTypeService.class)
@RemoteBinding(jndiBinding="ExamTypeService")
@TransactionManagement(TransactionManagementType.CONTAINER)
public class ExamTypeServiceImpl implements ExamTypeService{

	/**
	 * DAO instance.
	 */
	private ExamTypeDAO examTypeDao = (ExamTypeDAO)DAOFactory.getDAOInstance(ExamTypeDAO.class.getName());
	private ExamCategoryLevelMappingDAO examCategoryLevelMappingDao = (ExamCategoryLevelMappingDAO)DAOFactory.getDAOInstance(ExamCategoryLevelMappingDAO.class.getName());
	
	/**
	 * Logger instance.
	 */
	private Logger log = Logger.getLogger(ExamTypeServiceImpl.class.getName());

	public ExamType getExam(Long examTypeId) throws ServiceBeanException{
		log.debug("Entering :: ExamTypeServiceImpl:getExam()");
		try{
			if(examTypeId != null)
				return examTypeDao.read(examTypeId);
			else
				throw new ServiceBeanException(ErrorMessages.MANDATORY_PARAMETER_MISSING_EXCEPTION+" examTypeId");
		}
		catch(DAOException ex){
			log.error(ExamErrorMessages.EXAM_READ_EXCEPTION, ex);
			throw new EJBException(ex);
		}
	}
	
	public List<ExamType> fetchActiveExams() throws ServiceBeanException{
		log.debug("Entering :: ExamTypeServiceImpl:fetchActiveExams()");
		try{
			SearchVO searchVO = new SearchVO();
			searchVO.addEqualsCondition("status", StatusConstants.ACTIVE);
			return examTypeDao.search(searchVO);
		}
		catch(Exception ex){
			log.error(ExamErrorMessages.EXAM_READ_EXCEPTION, ex);
			throw new EJBException(ex);
		}
	}
	
	public List<ExamType> fetchExams(SearchVO searchVO) throws ServiceBeanException{
		log.debug("Entering :: ExamTypeServiceImpl:fetchExams()");
		try{
			return examTypeDao.search(searchVO);
		}
		catch(Exception ex){
			log.error(ExamErrorMessages.EXAM_READ_EXCEPTION, ex);
			throw new EJBException(ex);
		}
	}
	
	public ExamType createExam(ExamType examType, List<ExamCategoryLevelMapping> questionTypes) throws ServiceBeanException{
		log.debug("Entering :: ExamTypeServiceImpl:createExam()");
		try{
			// Perform business validations.
			// check for the mandatory parameters.
			if(examType.checkForMandatoryParameters() != null && examType.checkForMandatoryParameters().size() > 0){
				String errorMsg = ErrorMessages.MANDATORY_PARAMETER_MISSING_EXCEPTION;
				Iterator<String> iter = examType.checkForMandatoryParameters().iterator();
				while(iter.hasNext()){
					errorMsg = errorMsg+", "+iter.next();
				}
				throw new ServiceBeanException(errorMsg);
			}
			// Name uniqueness check.
			if(examTypeDao.verifyUnique("name", examType.getName(), null)){
				// Create the exam in database.
				examType = examTypeDao.create(examType);
				log.info("The new exam created with ID : "+examType.getId().longValue());
				
				for(ExamCategoryLevelMapping examCategoryLevelMapping : questionTypes){
					examCategoryLevelMapping.setExamType(examType);
					examCategoryLevelMapping.getId().setExamTypeId(examType.getId());
					examCategoryLevelMappingDao.create(examCategoryLevelMapping);
				}
				log.debug("Exiting :: ExamTypeServiceImpl:createExam()");
				return examType;
			}
			else{
				// Name already exists.
				throw new ServiceBeanException(ExamErrorMessages.EXAM_CREATE_DUPLICATE_NAME_EXCEPTION);
			}
		}
		catch(DAOException ex){
			log.error(ExamErrorMessages.EXAM_CREATE_EXCEPTION, ex);
			throw new EJBException(ex);
		}
	}
	
	public ExamType updateExam(ExamType examType, List<ExamCategoryLevelMapping> questionTypes) throws ServiceBeanException{
		log.debug("Entering :: ExamTypeServiceImpl:updateExam()");
		try{
			// Perform business validations.
			// check for the mandatory parameters.
			if(examType.checkForMandatoryParameters() != null && examType.checkForMandatoryParameters().size() > 0){
				String errorMsg = ErrorMessages.MANDATORY_PARAMETER_MISSING_EXCEPTION;
				Iterator<String> iter = examType.checkForMandatoryParameters().iterator();
				while(iter.hasNext()){
					errorMsg = errorMsg+", "+iter.next();
				}
				throw new ServiceBeanException(errorMsg);
			}
			// Name uniqueness check.
			if(examTypeDao.verifyUnique("name", examType.getName(), examType.getId())){
				// Update the exam in database.
				examType = examTypeDao.update(examType);
				log.info("The new exam updated with ID : "+examType.getId().longValue());
				
				// delete all the mappings for the exam.
				SearchVO searchVO = new SearchVO();
				searchVO.addEqualsCondition("examType.id", examType.getId(), true);
				List<ExamCategoryLevelMapping> tobeDeletedMappings = examCategoryLevelMappingDao.search(searchVO);
				if(questionTypes!=null && questionTypes.size()>0){
					for(ExamCategoryLevelMapping examCategoryLevelMapping : tobeDeletedMappings){
						examCategoryLevelMappingDao.delete(examCategoryLevelMapping.getId());
					}
				}
				
				for(ExamCategoryLevelMapping examCategoryLevelMapping : questionTypes){
					examCategoryLevelMapping.setExamType(examType);
					examCategoryLevelMapping.getId().setExamTypeId(examType.getId());
					examCategoryLevelMappingDao.create(examCategoryLevelMapping);
				}
				
				log.debug("Exiting :: ExamTypeServiceImpl:updateExam()");
				return examType;
			}
			else{
				// Name already exists.
				throw new ServiceBeanException(ExamErrorMessages.EXAM_CREATE_DUPLICATE_NAME_EXCEPTION);
			}
		}
		catch(DAOException ex){
			log.error(ExamErrorMessages.EXAM_UPDATE_EXCEPTION, ex);
			throw new EJBException(ex);
		}
	}
	
	public List<ExamCategoryLevelMapping> fetchExamCategoryLevelMapping(SearchVO searchVO) throws ServiceBeanException{
		log.debug("Entering :: ExamTypeServiceImpl:fetchExamCategoryLevelMapping()");
		try{
			return examCategoryLevelMappingDao.search(searchVO);
		}
		catch(Exception ex){
			log.error(ExamErrorMessages.EXAM_READ_EXCEPTION, ex);
			throw new EJBException(ex);
		}
	}
}
